package parser

import (
	"github.com/fatih/color"
	"github.com/hashicorp/hcl/v2"
	"github.com/ihaiker/tfwrapper/internal/config"
	"github.com/ihaiker/tfwrapper/internal/eval"
	"github.com/ihaiker/tfwrapper/internal/logger"
	"github.com/ihaiker/tfwrapper/internal/util"
)

func evaluateConstraint(config, super *config.Running, flags config.Flags, file *hcl.File) (err hcl.Diagnostics) {
	content, _, diags := file.Body.PartialContent(&hcl.BodySchema{
		Attributes: []hcl.AttributeSchema{
			{Name: "terraform_version_constraint"},
			{Name: "terraform_binary"},
			{Name: "tfwrapper_version_constraint"},
			{Name: "download_dir"},
			{Name: "auto_inputs"},
			{Name: "non_interactive"},
			{Name: "parallelism"},
		},
	})
	if diags.HasErrors() {
		return diags
	}

	log := logger.Logger(*config)
	ctx, diags := eval.CreateEvalContext(*config)
	if diags.HasErrors() {
		return diags
	}

	if flags.TerraformBinary != "" {
		config.TerraformBinary = util.StringPtr(flags.TerraformBinary)
		log.Debugf("use user-specified terraform binary: %s", *config.TerraformBinary)
	} else if config.TerraformBinary, err = ctx.AttrValueAsString(content.Attributes, "terraform_binary"); err != nil {
		return
	} else if config.TerraformBinary != nil {
		log.Debugf("use terraform binary: %s", color.HiYellowString(*config.TerraformBinary))
	} else if super != nil && super.TerraformBinary != nil {
		config.TerraformBinary = util.StringPtr(*super.TerraformBinary)
	}

	//terraform
	if config.TerraformVersionConstraint, err = ctx.AttrValueAsString(
		content.Attributes, "terraform_version_constraint"); err != nil {
		return
	} else if config.TerraformVersionConstraint != nil {
		log.Debugf("found terraform version constraint: %s", color.HiYellowString(*config.TerraformVersionConstraint))
	} else if super != nil && super.TerraformVersionConstraint != nil {
		config.TerraformVersionConstraint = util.StringPtr(*super.TerraformVersionConstraint)
	}

	//tfwrapper
	if config.TFWrapperVersionConstraint, err = ctx.AttrValueAsString(
		content.Attributes, "tfwrapper_version_constraint"); err != nil {
		return
	} else if config.TFWrapperVersionConstraint != nil {
		log.Debugf("found tfwrapper version constraint: %s", color.HiYellowString(*config.TFWrapperVersionConstraint))
	} else if super != nil && super.TFWrapperVersionConstraint != nil {
		config.TFWrapperVersionConstraint = util.StringPtr(*super.TFWrapperVersionConstraint)
	}

	if flags.DownloadDir != "" {
		config.DownloadDir = util.StringPtr(flags.DownloadDir)
		log.Debugf("use user-specified download dir: %s", *config.DownloadDir)
	} else {
		if config.DownloadDir, err = ctx.AttrValueAsString(content.Attributes, "download_dir"); err != nil {
			return
		} else if config.DownloadDir != nil {
			log.Debugf("found download dir: %s", *config.DownloadDir)
		} else if super != nil && super.DownloadDir != nil {
			config.DownloadDir = util.StringPtr(*super.DownloadDir)
		}
	}

	if config.AutoInputs, err = ctx.AttrValueAsBoolean(content.Attributes, "auto_inputs"); err != nil {
		return
	} else if config.AutoInputs != nil {
		log.Debugf("found auto inputs: %s", color.HiYellowString("%v", *config.AutoInputs))
	} else if super != nil && super.AutoInputs != nil {
		config.AutoInputs = util.BoolPtr(*super.AutoInputs)
	}

	if flags.NonInteractive != nil {
		config.NonInteractive = util.BoolPtr(*flags.NonInteractive)
		if super == nil {
			log.Debugf("use user-specified non interactive: %v", color.HiYellowString("%v", *config.NonInteractive))
		}
	} else if config.NonInteractive, err = ctx.AttrValueAsBoolean(content.Attributes, "non_interactive"); err != nil {
		return
	} else if config.NonInteractive != nil {
		log.Debugf("found non interactive: %s", color.HiYellowString("%v", *config.NonInteractive))
	} else if super != nil && super.NonInteractive != nil {
		config.NonInteractive = util.BoolPtr(*super.NonInteractive)
	}

	if config.Parallelism, err = ctx.AttrValueAsInt(content.Attributes, "parallelism"); err != nil {
		return
	} else if config.Parallelism != nil {
		log.Debugf("found parallelism: %s", color.HiYellowString("%v", *config.Parallelism))
	} else if super != nil && super.Parallelism != nil {
		config.Parallelism = util.UintPtr(*super.Parallelism)
	}
	return
}
